home *** CD-ROM | disk | FTP | other *** search
/ Otherware / Otherware_1_SB_Development.iso / mac / developm / language / harvest.cpt / Harvest C / CHarvestDoc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-06-16  |  47.5 KB  |  1,808 lines

  1. /*
  2.     Harvest C
  3.     Copyright 1992 Eric W. Sink.  All rights reserved.
  4.     
  5.     This file is part of Harvest C.
  6.     
  7.     Harvest C is free software; you can redistribute it and/or modify
  8.     it under the terms of the GNU Generic Public License as published by
  9.     the Free Software Foundation; either version 2, or (at your option)
  10.     any later version.
  11.     
  12.     Harvest C is distributed in the hope that it will be useful,
  13.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.     GNU General Public License for more details.
  16.     
  17.     You should have received a copy of the GNU General Public License
  18.     along with Harvest C; see the file COPYING.  If not, write to
  19.     the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  20.     
  21.     Harvest C is not in any way a product of the Free Software Foundation.
  22.     Harvest C is not GNU software.
  23.     Harvest C is not public domain.
  24.  
  25.     This file may have other copyrights which are applicable as well.
  26.  
  27. */
  28.  
  29. /****
  30.  * CHarvestDoc.c
  31.  *
  32.  *    Document methods for Harvest C
  33.  *
  34.  *  Copyright ⌐ 1990 Symantec Corporation.  All rights reserved.
  35.  *
  36.  ****/
  37.  
  38. #include "Global.h"
  39. #include "Constants.h"
  40. #include "Commands.h"
  41. #include "CApplication.h"
  42. #include "CBartender.h"
  43. #include "CDataFile.h"
  44. #include "CDecorator.h"
  45. #include "CDesktop.h"
  46. #include "CError.h"
  47. #include "CPanorama.h"
  48. #include "CScrollPane.h"
  49. #include "CHarvestApp.h"
  50. #include "CHarvestDoc.h"
  51. #include "CHarvestOptions.h"
  52. #include "CHarvestPane.h"
  53. #include "COptionsDialog.h"
  54. #include "CProjectInfoDialog.h"
  55. #include "CCheckBox.h"
  56. #include "CRadioControl.h"
  57. #include "CRadioGroupPane.h"
  58. #include "CWarningsDialog.h"
  59. #include "CWarningsArray.h"
  60. #include "CDialogText.h"
  61. #include "CIntegerText.h"
  62. #include "TBUtilities.h"
  63. #include "CWindow.h"
  64. #include "CFile.h"
  65. #include "CList.h"
  66. #include "CResourceFile.h"
  67. #include "CSourceFile.h"
  68. #include "CLibraryFile.h"
  69. #include <Packages.h>
  70. #include "AppleEvents.h"
  71. #include "Aliases.h"
  72. #include "HarvestCommands.h"
  73. #include "CErrorLog.h"
  74. #include "structs.h"
  75. #include "linkstruct.h"
  76.  
  77. #define    WINDHarvest        500        /* Resource ID for WIND template */
  78.  
  79. extern    CHarvestApp *gApplication;    /* The application */
  80. extern    tSystem        gSystem;
  81. extern    CHarvestDoc    *gProject;
  82. extern    CErrorLog    *gErrs;
  83. extern    CSourceFile *gCurSourceFile;
  84. extern    CBartender    *gBartender;    /* The menu handling object */
  85. extern    CDecorator    *gDecorator;    /* Window dressing object    */
  86. extern    CDesktop    *gDesktop;        /* The enclosure for all windows */
  87. extern    CBureaucrat    *gGopher;        /* The current boss in the chain of command */
  88. extern    OSType        gSignature;        /* The application's signature */
  89. extern    CError        *gError;        /* The global error handler */
  90. extern    int                             LinkErrorCount;
  91. extern    SegmentVia_t                    SegmentList;
  92. extern    DATAZone_t                      theDATA;
  93. extern    CursHandle            gWatchCursor;        /* Watch cursor for waiting            */
  94.  
  95. enum {
  96.     kTrigraphsItem = 4,
  97.     kBigGlobalsItem,
  98.     k68020Item,
  99.     k68881Item,
  100.     kSignedCharItem,
  101.     kMacsBugitem
  102. };
  103.  
  104. enum {
  105.     kSigFieldItem = 3,
  106.     kPartitionItem,
  107.     kSizeFlagsItem
  108. };
  109.  
  110. Boolean FindAProcess(OSType signature,ProcessSerialNumber *process,
  111.                         ProcessInfoRec *InfoRec,
  112.                         FSSpecPtr aFSSpecPtr)
  113. {
  114.     process->highLongOfPSN = 0;
  115.     process->lowLongOfPSN = kNoProcess;
  116.     
  117.     InfoRec->processInfoLength = sizeof(ProcessInfoRec);
  118.     InfoRec->processName = (StringPtr) NewPtr(32);
  119.     InfoRec->processAppSpec = aFSSpecPtr;
  120.     
  121.     while (GetNextProcess(process) == noErr) {
  122.         if (GetProcessInformation(process,InfoRec) == noErr) {
  123.             if ((InfoRec->processType == 'APPL') &&
  124.                 (InfoRec->processSignature == signature)) {
  125.                 return TRUE;
  126.             }
  127.         }
  128.     }
  129.     return FALSE;
  130. }
  131.  
  132.  
  133.  
  134. /***
  135.  * IHarvestDoc
  136.  *
  137.  *    This is your document's initialization method.
  138.  *    If your document has its own instance variables, initialize
  139.  *    them here.
  140.  *
  141.  *    The least you need to do is invoke the default method.
  142.  *
  143.  ***/
  144.  
  145. void CHarvestDoc::IHarvestDoc(CApplication *aSupervisor, Boolean printable)
  146.  
  147. {
  148.     CDocument::IDocument(aSupervisor, printable);
  149.  
  150.     itsSourceFiles = new(CList);
  151.     itsSourceFiles->IList();
  152.     itsOptions = new CHarvestOptions;
  153.     itsOptions->IHarvestOptions();
  154.     itsWarnings = new CWarningsArray;
  155.     itsWarnings->IWarningsArray(itsOptions);
  156.     itsWarnings->AddWarning("\pEmpty expression stmt",WARN_emptystatement,TRUE);
  157.     itsWarnings->AddWarning("\pMulti-character constant",WARN_multicharconstant,FALSE);
  158.     itsWarnings->AddWarning("\pRedundant cast",WARN_redundantcast,FALSE);
  159.     itsWarnings->AddWarning("\pEquivalence test of floating type",WARN_floateqcompare,TRUE);
  160.     itsWarnings->AddWarning("\pDiscarded function result",WARN_discardfuncresult,FALSE);
  161.     itsWarnings->AddWarning("\pAssignment as if conditional",WARN_assignif,TRUE);
  162.     itsWarnings->AddWarning("\pNon-void function has no return statement",WARN_nonvoidreturn,TRUE);
  163.     itsWarnings->AddWarning("\pConstant expression as if condition",WARN_constantif,TRUE);
  164.     itsWarnings->AddWarning("\pComparison of pointer and integer",WARN_comparepointerint,TRUE);
  165.     itsWarnings->AddWarning("\pAssignment of nonequivalent type to a pointer",WARN_pointernonequivassign,TRUE);
  166.     itsWarnings->AddWarning("\pReturn of nonequivalent type to a pointer",WARN_pointernonequivreturn,TRUE);
  167.     itsWarnings->AddWarning("\pPass of nonequivalent type to a pointer",WARN_pointernonequivarg,TRUE);
  168.     itsWarnings->AddWarning("\pConstant expression as switch condition",WARN_constantswitch,TRUE);
  169.     itsWarnings->AddWarning("\pConstant expression as while loop condition",WARN_constantwhile,TRUE);
  170.     itsWarnings->AddWarning("\pConstant expression as do-while loop condition",WARN_constantdowhile,TRUE);
  171.     itsWarnings->AddWarning("\pConstant expression as for loop condition",WARN_constantfor,TRUE);
  172.     itsWarnings->AddWarning("\pSwitch expression not of integral type",WARN_nonintegralswitch,TRUE);
  173.     itsWarnings->AddWarning("\pVolatile is not handled by this compiler",WARN_novolatile,TRUE);
  174.     itsWarnings->AddWarning("\pUnused variable: ",WARN_unusedvariable,TRUE);
  175.     itsWarnings->AddWarning("\pDead code",WARN_deadcode,TRUE);
  176.     itsWarnings->AddWarning("\pImplicit decl : ",WARN_implicitdecl,FALSE);
  177.     itsWarnings->AddWarning("\pRe#definition : ",WARN_preprocredef,FALSE);
  178.     itsWarnings->AddWarning("\pPossible nested comment",WARN_nestedcomment,TRUE);
  179.     itsWarnings->AddWarning("\pgoto statement found",WARN_goto,TRUE);
  180.     itsWarnings->AddWarning("\pMultiple function returns",WARN_multireturn,TRUE);
  181.     itsWarnings->AddWarning("\pEmpty compound statement",WARN_emptycompound,TRUE);
  182.     itsWarnings->AddWarning("\pMissing function return type - default to int",WARN_missingreturntype,TRUE);
  183.     itsWarnings->AddWarning("\pTrigraph found",WARN_trigraphs,TRUE);
  184.     itsWarnings->AddWarning("\ppascal keyword found",WARN_pascal,FALSE);
  185.     itsWarnings->AddWarning("\pSemicolon after function body",WARN_semiafterfunction,TRUE);
  186.  
  187.     itsPrefix = NULL;
  188.     StdAppVol = -1;
  189.     StdAppDir = -1;
  190.     CopyPString("\papp.out",StdAppName);
  191.     itsPartition = 384*1024;
  192.     itsSignature = '????';
  193.     itsSizeFlags = 0;
  194.     gProject = this;
  195. }
  196.  
  197. /***
  198.  * AddLibraryFileHFS
  199.  *
  200.  *
  201.  ***/
  202.  
  203. void CHarvestDoc::AddLibraryFileHFS(Str63 aName,short aVolNum,long aDirID)
  204.  
  205. {
  206.     CDataFile *newFile;
  207.     CLibraryFile *newLibraryFile;
  208.     newFile = new(CDataFile);
  209.     newFile->IDataFile();
  210.     newFile->SpecifyHFS(aName,aVolNum,aDirID);
  211.     newLibraryFile = new(CLibraryFile);
  212.     newLibraryFile->ILibraryFile(newFile);
  213.     itsSourceFiles->Append((CObject *) newLibraryFile);
  214.     itsTable->AddRow(1,-1);
  215. }
  216.  
  217. /***
  218.  * AddSourceFileHFS
  219.  *
  220.  *
  221.  ***/
  222.  
  223. void CHarvestDoc::AddSourceFileHFS(Str63 aName,short aVolNum,long aDirID)
  224.  
  225. {
  226.     CDataFile *newFile;
  227.     CSourceFile *newSourceFile;
  228.     newFile = new(CDataFile);
  229.     newFile->IDataFile();
  230.     newFile->SpecifyHFS(aName,aVolNum,aDirID);
  231.     newSourceFile = new(CSourceFile);
  232.     newSourceFile->ISourceFile(newFile);
  233.     itsSourceFiles->Append((CObject *) newSourceFile);
  234.     itsTable->AddRow(1,-1);
  235. }
  236.  
  237. /***
  238.  * AddSourceFile
  239.  *
  240.  *
  241.  ***/
  242.  
  243. void CHarvestDoc::AddSourceFile(SFReply *theFile)
  244.  
  245. {
  246.     CDataFile *newFile;
  247.     FInfo fileInfo;
  248.     CSourceFile *newSourceFile;
  249.     CLibraryFile *newLibFile;
  250.     CResourceFile *newResourceFile;
  251.     newFile = new(CDataFile);
  252.     newFile->IDataFile();
  253.     newFile->SFSpecify(theFile);
  254.     /* Here, we check the format of the name and the file type, and add the
  255.        appropriate object, library/source/resource to the project */
  256.     newFile->GetMacFileInfo(&fileInfo);
  257.     if (fileInfo.fdType == 'TEXT') {
  258.         newSourceFile = new(CSourceFile);
  259.         newSourceFile->ISourceFile(newFile);
  260.         itsSourceFiles->Append((CObject *) newSourceFile);
  261.         itsTable->AddRow(1,-1);
  262.     }
  263.     else if (fileInfo.fdType == 'OBJ ') {
  264.         newLibFile = new(CLibraryFile);
  265.         newLibFile->ILibraryFile(newFile);
  266.         itsSourceFiles->Append((CObject *) newLibFile);
  267.         itsTable->AddRow(1,-1);
  268.     }
  269.     else if (fileInfo.fdCreator == 'RSED') {
  270.         newResourceFile = new(CResourceFile);
  271.         newResourceFile->IResourceFile(newFile);
  272.         itsSourceFiles->Append((CObject *) newResourceFile);
  273.         itsTable->AddRow(1,-1);
  274.     }
  275.     else if (fileInfo.fdType == 'rsrc') {
  276.         newResourceFile = new(CResourceFile);
  277.         newResourceFile->IResourceFile(newFile);
  278.         itsSourceFiles->Append((CObject *) newResourceFile);
  279.         itsTable->AddRow(1,-1);
  280.     }
  281. }
  282.  
  283. /***
  284.  * AddResourceFileHFS
  285.  *
  286.  *
  287.  ***/
  288.  
  289. void CHarvestDoc::AddResourceFileHFS(Str63 aName,short aVolNum,long aDirID)
  290.  
  291. {
  292.     CDataFile *newFile;
  293.     CResourceFile *newResourceFile;
  294.     newFile = new(CDataFile);
  295.     newFile->IDataFile();
  296.     newFile->SpecifyHFS(aName,aVolNum,aDirID);
  297.     newResourceFile = new(CResourceFile);
  298.     newResourceFile->IResourceFile(newFile);
  299.     itsSourceFiles->Append((CObject *) newResourceFile);
  300.     itsTable->AddRow(1,-1);
  301. }
  302.  
  303. /***
  304.  * AddResourceFile
  305.  *
  306.  *
  307.  ***/
  308.  
  309. void CHarvestDoc::AddResourceFile(SFReply *theFile)
  310.  
  311. {
  312.     CDataFile *newFile;
  313.     CResourceFile *newResourceFile;
  314.     newFile = new(CDataFile);
  315.     newFile->IDataFile();
  316.     newFile->SFSpecify(theFile);
  317.     newResourceFile = new(CResourceFile);
  318.     newResourceFile->IResourceFile(newFile);
  319.     itsSourceFiles->Append((CObject *) newResourceFile);
  320.     itsTable->AddRow(1,-1);
  321. }
  322.  
  323. /***
  324.  * AddLibFile
  325.  *
  326.  *
  327.  ***/
  328.  
  329. void CHarvestDoc::AddLibFile(SFReply *theFile)
  330.  
  331. {
  332.     CDataFile *newFile;
  333.     CLibraryFile *newSourceFile;
  334.     newFile = new(CDataFile);
  335.     newFile->IDataFile();
  336.     newFile->SFSpecify(theFile);
  337.     newSourceFile = new(CLibraryFile);
  338.     newSourceFile->ILibraryFile(newFile);
  339.     itsSourceFiles->Append((CObject *) newSourceFile);
  340.     itsTable->AddRow(1,-1);
  341. }
  342.  
  343. /***
  344.  * Dispose
  345.  *
  346.  *    This is your document's destruction method.
  347.  *    If you allocated memory in your initialization method
  348.  *    or opened temporary files, this is the place to release them.
  349.  *
  350.  *    Be sure to call the default method!
  351.  *
  352.  ***/
  353.  
  354. void CHarvestDoc::Dispose(void)
  355.  
  356. {
  357. #ifdef Undefined    /* caused illegal inst 5 March */
  358.     itsSourceFiles->Dispose();
  359.     itsOptions->Dispose();
  360.     itsWarnings->Dispose();
  361. #endif
  362.     inherited::Dispose();
  363. }
  364.  
  365. void CHarvestDoc::DoOptions(CHarvestOptions *theOpts)
  366. {
  367.     COptionsDialog *dialog;
  368.     long cmd;
  369.     CCheckBox *trigraphsBox;
  370.     CCheckBox *globalsBox;
  371.     CCheckBox *mc68020Box;
  372.     CCheckBox *mc68881Box;
  373.     CCheckBox *signedCharsBox;
  374.     CCheckBox *MacsBugBox;
  375.  
  376.     dialog = new COptionsDialog;
  377.     dialog->IOptionsDialog(500,this);
  378.     
  379.     /* Now initialize states of the boxes */
  380.     trigraphsBox = (CCheckBox *) dialog->itsWindow->FindViewByID( kTrigraphsItem);
  381.     globalsBox = (CCheckBox *) dialog->itsWindow->FindViewByID( kBigGlobalsItem);
  382.     mc68020Box = (CCheckBox *) dialog->itsWindow->FindViewByID( k68020Item);
  383.     mc68881Box = (CCheckBox *) dialog->itsWindow->FindViewByID( k68881Item);
  384.     signedCharsBox = (CCheckBox *) dialog->itsWindow->FindViewByID( kSignedCharItem);
  385.     MacsBugBox = (CCheckBox *) dialog->itsWindow->FindViewByID( kMacsBugitem);
  386.     
  387.     trigraphsBox->SetValue(theOpts->trigraphs ? BUTTON_ON : BUTTON_OFF);
  388.     globalsBox->SetValue(theOpts->bigGlobals ? BUTTON_ON : BUTTON_OFF);
  389.     mc68020Box->SetValue(theOpts->useMC68020 ? BUTTON_ON : BUTTON_OFF);
  390.     mc68881Box->SetValue(theOpts->useMC68881 ? BUTTON_ON : BUTTON_OFF);
  391.     signedCharsBox->SetValue(theOpts->signedChars ? BUTTON_ON : BUTTON_OFF);
  392.     MacsBugBox->SetValue(theOpts->MacsBugSymbols ? BUTTON_ON : BUTTON_OFF);
  393.  
  394.     
  395.     dialog->BeginDialog();
  396.     cmd = dialog->DoModalDialog(cmdOK);
  397.     if (cmd == cmdOK)
  398.     {
  399.         theOpts->trigraphs = trigraphsBox->IsChecked();
  400.         theOpts->bigGlobals = globalsBox->IsChecked();
  401.         theOpts->useMC68020 = mc68020Box->IsChecked();
  402.         theOpts->useMC68881 = mc68881Box->IsChecked();
  403.         theOpts->signedChars = signedCharsBox->IsChecked();
  404.         theOpts->MacsBugSymbols = MacsBugBox->IsChecked();
  405.     }
  406.     ForgetObject(dialog);
  407. }
  408.  
  409. void CHarvestDoc::DoWarnings(CHarvestOptions *theOpts,CWarningsArray *theWarnings)
  410. {
  411.     CWarningsDialog *dialog;
  412.     long cmd;
  413.  
  414.     dialog = new CWarningsDialog;
  415.     dialog->IWarningsDialog(theOpts,theWarnings);
  416.     
  417.     dialog->BeginDialog();
  418.     cmd = dialog->DoModalDialog(cmdOK);
  419.     if (cmd == cmdOK)
  420.     {
  421.     }
  422.     ForgetObject(dialog);
  423. }
  424.  
  425. char *OSTypeToString(OSType val,char *s)
  426. {
  427.     *((long *) s) = val;
  428.     s[4] = 0;
  429.     return s;
  430. }
  431.  
  432. void CHarvestDoc::DoSetProjectInfo(void)
  433. {
  434.     Str255 theSig;
  435.     CProjectInfoDialog *dialog;
  436.     long cmd;
  437.     CDialogText *sigField;
  438.     CIntegerText *partitionField;
  439.     CIntegerText *sizeFlagsField;
  440.     char sigString[8];
  441.  
  442.     dialog = new CProjectInfoDialog;
  443.     dialog->IProjectInfoDialog(501,this);
  444.     
  445.     sigField = (CDialogText *) dialog->itsWindow->FindViewByID( kSigFieldItem);
  446.     partitionField = (CIntegerText *) dialog->itsWindow->FindViewByID( kPartitionItem);
  447.     sizeFlagsField = (CIntegerText *) dialog->itsWindow->FindViewByID( kSizeFlagsItem);
  448.  
  449.     /* Now initialize states of the textfields */
  450.     
  451.     OSTypeToString(itsSignature,sigString);
  452.     c2pstr(sigString);
  453.     sigField->SetTextString((unsigned char *) sigString);
  454.     partitionField->SetIntValue(itsPartition/1024);
  455.     sizeFlagsField->SetIntValue(itsSizeFlags);
  456.  
  457.     dialog->BeginDialog();
  458.     cmd = dialog->DoModalDialog(cmdOK);
  459.     if (cmd == cmdOK)
  460.     {
  461.         sigField->GetTextString(theSig);
  462.         p2cstr(theSig);
  463.         itsSignature = MakeOSType((char *) theSig);
  464.         itsPartition = partitionField->GetIntValue()*1024;
  465.         itsSizeFlags = sizeFlagsField->GetIntValue();
  466.     }
  467.     ForgetObject(dialog);
  468. }
  469.  
  470. /***
  471.  * DoCommand
  472.  *
  473.  *    This is the heart of your document.
  474.  *    In this method, you handle all the commands your document
  475.  *    deals with.
  476.  *
  477.  *    Be sure to call the default method to handle the standard
  478.  *    document commands: cmdClose, cmdSave, cmdSaveAs, cmdRevert,
  479.  *    cmdPageSetup, cmdPrint, and cmdUndo. To change the way these
  480.  *    commands are handled, override the appropriate methods instead
  481.  *    of handling them here.
  482.  *
  483.  ***/
  484.  
  485. void CHarvestDoc::DoCommand(long theCommand)
  486.  
  487. {
  488.     SFReply theFile;
  489.     Cell aCell = {0,0};
  490.     Boolean thereIsASelection = false;
  491.             if (itsTable->GetSelect(false,&aCell)) {
  492.                 thereIsASelection = true;
  493.             }
  494.             else if (itsTable->GetSelect(true,&aCell)) {
  495.                 thereIsASelection = true;
  496.             }
  497.     switch (theCommand) {
  498.  
  499.         case cmdAddCFile:
  500.                 gApplication->ChooseSourceFile(&theFile);
  501.                 if (theFile.good) {
  502.                     AddSourceFile(&theFile);
  503.                 }
  504.                 break;
  505.         case cmdRemove:
  506.             /* Remove the currently selected file */
  507.             if (thereIsASelection) {
  508.                 /* Delete the item from the itsSourceFiles list and
  509.                     the row from the table */
  510.                 itsSourceFiles->Remove(itsSourceFiles->NthItem(aCell.v+1));
  511.                 itsTable->DeleteRow(1,aCell.v);
  512.                 itsTable->DeselectAll(true);
  513.             }
  514.         break;
  515.         case cmdOpenSourceFile:
  516.             if (thereIsASelection) {
  517.                 OSType theSig;
  518.                 CSourceFile *theSourceFile = (CSourceFile *) itsSourceFiles->NthItem(aCell.v+1);
  519.                 theSig = 0;
  520.                 if (theSourceFile->itsKind == H_ResourceFile) theSig = 'RSED';
  521.                 else if (theSourceFile->itsKind == H_SourceFile) theSig = 'ALFA';
  522.                 else theSig = 0;
  523.                 gApplication->InspectSystem();
  524.                 if (gSystem.hasAppleEvents && theSig)
  525.                 {
  526.                     AERecord ae;
  527.                     AEDescList aeList;
  528.                     AEDesc docDesc;
  529.                     AEAddressDesc alfa;
  530.                     AliasHandle withThis;
  531.                     OSErr err;
  532.                     FSSpec theSpec;
  533.                     
  534.                     FSMakeFSSpec(theSourceFile->theFile->volNum,
  535.                                 theSourceFile->theFile->dirID,
  536.                                 theSourceFile->theFile->name,
  537.                                 &theSpec);
  538.                     err = AECreateDesc(typeApplSignature,(Ptr) &theSig,(Size) sizeof(theSig),&alfa);
  539.                     FailOSErr(err);
  540.                     err = AECreateAppleEvent(kCoreEventClass,kAEOpenDocuments,&alfa,kAutoGenerateReturnID,
  541.                         kAnyTransactionID,&ae);
  542.                     FailOSErr(err);
  543.                     err = AECreateList(NULL,0,FALSE,&aeList);
  544.                     FailOSErr(err);
  545.                     NewAlias(NULL,&theSpec,&withThis);
  546.                     HLock((Handle) withThis);
  547.                     err = AECreateDesc(typeAlias,(Ptr) *withThis, GetHandleSize((Handle) withThis),
  548.                         &docDesc);
  549.                     FailOSErr(err);
  550.                     HUnlock((Handle) withThis);
  551.                     err = AEPutDesc(&aeList,0,&docDesc);
  552.                     FailOSErr(err);
  553.                     err = AEPutParamDesc(&ae,keyDirectObject,&aeList);
  554.                     FailOSErr(err);
  555.                     err = AESend(&ae,NULL,kAENoReply,kAENormalPriority,0,NULL,NULL);
  556.                     FailOSErr(err);
  557.                     if (!err) {
  558.                         ProcessSerialNumber process;
  559.                         ProcessInfoRec InfoRec;
  560.                         FSSpec theSpec;
  561.                         if (FindAProcess(theSig,&process,&InfoRec,&theSpec)) {
  562.                             SetFrontProcess(&process);
  563.                         }
  564.                     }
  565.                 }
  566.             }
  567.         break;
  568.         case cmdCompile:
  569.             /* Compile the currently selected file */
  570.             if (thereIsASelection) {
  571.                 CSourceFile *theFile;
  572.                 theFile = ((CSourceFile *) itsSourceFiles->NthItem(aCell.v+1));
  573.                 if (theFile->itsKind == H_SourceFile) {
  574.                     theFile->Compile();
  575.                 }
  576.             }
  577.         break;
  578.         case cmdSetProjectInfo:
  579.             DoSetProjectInfo();
  580.         break;
  581.         case cmdOptions:
  582.             DoOptions(itsOptions);
  583.         break;
  584.         case cmdWarnings:
  585.             DoWarnings(itsOptions,itsWarnings);
  586.         break;
  587.         case cmdSave:
  588.             SysBeep(1);
  589.             break;
  590.         case cmdCloseProject:
  591.         case cmdClose:
  592.             this->Close(false);
  593.             break;
  594.     
  595.         case cmdBringUpToDate:
  596.             BringUpToDate();
  597.             break;
  598.         case cmdRun:
  599.             RunApp();
  600.             break;
  601.         case cmdBuildApplication:
  602.             Link();
  603.             break;
  604.         case cmdCheckLink:
  605.             CheckLink();
  606.             break;
  607.         case cmdClean:
  608.             Clean();
  609.             break;
  610.  
  611.         default:    inherited::DoCommand(theCommand);
  612.                     break;
  613.     }
  614. }
  615.  
  616.  
  617. /***
  618.  * UpdateMenus
  619.  *
  620.  *  In this method you can enable menu commands that apply when
  621.  *  your document is active.
  622.  *
  623.  *  Be sure to call the inherited method to get the default behavior.
  624.  *  The inherited method enables these commands: cmdClose, cmdSaveAs,
  625.  *  cmdSave, cmdRevert, cmdPageSetup, cmdPrint, cmdUndo.
  626.  *
  627. ***/
  628.  
  629.  void CHarvestDoc::UpdateMenus()
  630.  
  631.  {
  632.      Cell aCell = {0,0};
  633.      Boolean thereIsASelection = false;
  634.     CSourceFile *theSourceFile;
  635.     inherited::UpdateMenus();
  636.  
  637.     /* Enable your menu commands here (enable each one with a call to   
  638.        gBartender->EnableCmd(command_number)).  
  639.     */                      
  640.     gBartender->EnableCmd(cmdAddCFile);
  641.     /* others in the Sources menu will be enabled when there are actually
  642.         things in the project */
  643.     if (itsTable->GetSelect(false,&aCell)) {
  644.         thereIsASelection = true;
  645.     }
  646.     else if (itsTable->GetSelect(true,&aCell)) {
  647.         thereIsASelection = true;
  648.     }
  649.     theSourceFile = (CSourceFile *) itsSourceFiles->NthItem(aCell.v+1);
  650.     if (thereIsASelection) {
  651.         gBartender->EnableCmd(cmdRemove);
  652.         gBartender->DisableCmd(cmdGetInfo);
  653.         if (theSourceFile->itsKind == H_SourceFile) {
  654.             /* TODO enable these when they are implemented */
  655.             gBartender->DisableCmd(cmdCheckSyntax);
  656.             gBartender->DisableCmd(cmdPreprocess);
  657.             gBartender->EnableCmd(cmdCompile);
  658.             gBartender->EnableCmd(cmdOpenSourceFile);
  659.         }
  660.         else if (theSourceFile->itsKind == H_ResourceFile) {
  661.             gBartender->EnableCmd(cmdOpenSourceFile);
  662.         }
  663.     }
  664.         
  665.     gBartender->DisableCmd(cmdSave);   
  666.     gBartender->DisableCmd(cmdSaveAs);
  667.     gBartender->DisableCmd(cmdNewProject);
  668.     gBartender->DisableCmd(cmdNew);
  669.     gBartender->DisableCmd(cmdOpenProject);
  670.     gBartender->DisableCmd(cmdOpen);
  671.     gBartender->EnableCmd(cmdOptions);
  672.     gBartender->EnableCmd(cmdWarnings);
  673.     gBartender->EnableCmd(cmdCloseProject);
  674.     gBartender->EnableCmd(cmdClose);
  675.     gBartender->EnableCmd(cmdSetProjectInfo);
  676.     gBartender->EnableCmd(cmdClean);
  677.     gBartender->EnableCmd(cmdBuildApplication);
  678.     gBartender->DisableCmd(cmdCheckLink);
  679.     gBartender->EnableCmd(cmdBringUpToDate);
  680.     gBartender->EnableCmd(cmdRun);
  681.     gBartender->DisableCmd(cmdPrint);
  682.  }
  683.  
  684.  
  685. /***
  686.  * FSNewFile
  687.  *
  688.  ***/
  689. void CHarvestDoc::FSNewFile(char *name, short vRefNum, long dirID)
  690.  
  691. {    
  692.     Str255  wTitle;     /* Window title string.         */
  693.     short   wCount;     /* Index number of new window.  */
  694.     Str255  wNumber;    /* Index number as a string.    */
  695.     CDataFile *theFile;
  696.     
  697.         /**
  698.          **    BuildWindow() is the method that
  699.          **    does the work of creating a window.
  700.          ** Its parameter should be the data that
  701.          **    you want to display in the window.
  702.          **    Since this is a new window, there's nothing
  703.          **    to display.
  704.          **
  705.          **/
  706.  
  707.     BuildWindow(NULL);
  708.  
  709.     theFile = new(CDataFile);
  710.     theFile->IDataFile();
  711.     theFile->SpecifyHFS((unsigned char *) name,vRefNum,dirID);
  712.     
  713.     
  714.         /**
  715.          ** Append an index number to the
  716.          ** default name of the window.
  717.          **/
  718.     theFile->GetName(wTitle);
  719.     if (theFile->ExistsOnDisk())
  720.         theFile->ThrowOut();
  721.     theFile->CreateNew(gSignature,'Hprj');
  722.     theFile->Open(fsWrPerm);
  723.  
  724.     itsFile = theFile;
  725.     itsWindow->SetTitle(wTitle);
  726.  
  727.         /**
  728.          **    Send the window a Select() message to make
  729.          **    it the active window.
  730.          **/
  731.     
  732.     itsWindow->Select();
  733.     
  734.     if (gApplication->StdLibVol || gApplication->StdLibDir) {
  735.         AddLibraryFileHFS("\pInterface.o",gApplication->StdLibVol,
  736.             gApplication->StdLibDir);
  737.         AddLibraryFileHFS("\pRuntime.o",gApplication->StdLibVol,
  738.             gApplication->StdLibDir);
  739.     }
  740. }
  741.  
  742. /***
  743.  * NewFile
  744.  *
  745.  *    When the user chooses New from the File menu, the CreateDocument()
  746.  *    method in your Application class will send a newly created document
  747.  *    this message. This method needs to create a new window, ready to
  748.  *    work on a new document.
  749.  *
  750.  *    Since this method and the OpenFile() method share the code for creating
  751.  *    the window, you should use an auxiliary window-building method.
  752.  *
  753.  ***/
  754. void CHarvestDoc::NewFile(void)
  755.  
  756. {    
  757.     Str255  wTitle;     /* Window title string.         */
  758.     short   wCount;     /* Index number of new window.  */
  759.     Str255  wNumber;    /* Index number as a string.    */
  760.     SFReply macSFReply;
  761.     CDataFile *theFile;
  762.     
  763.         /**
  764.          **    BuildWindow() is the method that
  765.          **    does the work of creating a window.
  766.          ** Its parameter should be the data that
  767.          **    you want to display in the window.
  768.          **    Since this is a new window, there's nothing
  769.          **    to display.
  770.          **
  771.          **/
  772.  
  773.     PickFileName(&macSFReply);
  774.     if (macSFReply.good) {
  775.         BuildWindow(NULL);
  776.     
  777.         theFile = new(CDataFile);
  778.         theFile->IDataFile();
  779.         theFile->SFSpecify(&macSFReply);
  780.         
  781.         
  782.             /**
  783.              ** Append an index number to the
  784.              ** default name of the window.
  785.              **/
  786.         theFile->GetName(wTitle);
  787.         if (theFile->ExistsOnDisk())
  788.             theFile->ThrowOut();
  789.         theFile->CreateNew(gSignature,'Hprj');
  790.         theFile->Open(fsWrPerm);
  791.     
  792.         itsFile = theFile;
  793.         itsWindow->SetTitle(wTitle);
  794.     
  795.             /**
  796.              **    Send the window a Select() message to make
  797.              **    it the active window.
  798.              **/
  799.         
  800.         itsWindow->Select();
  801.         
  802.         if (gApplication->StdLibVol || gApplication->StdLibDir) {
  803.             AddLibraryFileHFS("\pInterface.o",gApplication->StdLibVol,
  804.                 gApplication->StdLibDir);
  805.             AddLibraryFileHFS("\pRuntime.o",gApplication->StdLibVol,
  806.                 gApplication->StdLibDir);
  807.         }
  808.     }
  809. }
  810.  
  811.  
  812. /***
  813.  * OpenFile
  814.  *
  815.  *    When the user chooses Open╔ from the File menu, the OpenDocument()
  816.  *    method in your Application class will let the user choose a file
  817.  *    and then send a newly created document this message. The information
  818.  *    about the file is in the SFReply record.
  819.  *
  820.  *    In this method, you need to open the file and display its contents
  821.  *    in a window. This method uses the auxiliary window-building method.
  822.  *
  823.  ***/
  824.  
  825. void CHarvestDoc::OpenFile(SFReply *macSFReply)
  826.  
  827. {
  828.     CDataFile    *theFile;
  829.     Handle        theData = NULL;
  830.     Str63        theName;
  831.     FInfo        fileInfo;
  832.     OSErr        theError;
  833.     
  834.     TRY
  835.     {
  836.     
  837.             /**
  838.              ** Create a file and send it a SFSpecify()
  839.              **    message to set up the name, volume, and
  840.              **    directory.
  841.              **
  842.              **/
  843.     
  844.         theFile = new(CDataFile);
  845.         theFile->IDataFile();
  846.         theFile->SFSpecify(macSFReply);
  847.         theFile->GetMacFileInfo(&fileInfo);
  848.         if (fileInfo.fdType != 'Hprj') {
  849.             Failure(kSilentErr,0);
  850.         }
  851.             /**
  852.              **    Be sure to set the instance variable
  853.              **    so other methods can use the file if they
  854.              **    need to. This is especially important if
  855.              **    you leave the file open in this method.
  856.              **    If you close the file after reading it, you
  857.              **    should be sure to set itsFile to NULL.
  858.              **
  859.              **/
  860.     
  861.         itsFile = theFile;
  862.  
  863.             /**
  864.              **    Send the file an Open() message to
  865.              **    open it. You can use the ReadSome() or
  866.              **    ReadAll() methods to get the contents of the file.
  867.              **
  868.              **/
  869.     
  870.         theFile->Open(fsRdWrPerm);
  871.         
  872.             /**
  873.              **    Make sure that the memory request to read
  874.              **    the data from the file doesn't use up any
  875.              **    of our rainy day fund and that the GrowMemory()
  876.              **    method (in the application) knows that it's OK
  877.              **    if we couldn't get enough memory.
  878.              **
  879.              **/
  880.     
  881.     
  882.         theData = theFile->ReadAll();     /* ReadAll() creates the handle */
  883.         
  884.         if (!theData) {
  885.             Failure(kSilentErr,0);
  886.         }
  887.         
  888.         BuildWindow(theData);
  889.     
  890.         if (StdAppName[0] == 0) {
  891.             itsFile->GetName(StdAppName);
  892.         }
  893.         if (StdAppName[StdAppName[0]] == '╣') {
  894.             if (StdAppName[StdAppName[0]-1] == '.') {
  895.                 StdAppName[0] -= 2;
  896.             }
  897.             else {
  898.                 StdAppName[0] -= 1;
  899.             }
  900.         }
  901.             /**
  902.              **    In your application, you'll probably store
  903.              **    the data in some form as an instance variable
  904.              **    in your document class. For this example, there's
  905.              **    no need to save it, so we'll get rid of it.
  906.              **
  907.              **/
  908.     
  909.         DisposHandle(theData);
  910.         theData = NULL;
  911.     
  912.             /**
  913.              **    In this implementation, we leave the file
  914.              **    open. You might want to close it after
  915.              **    you've read in all the data.
  916.              **
  917.              **/
  918.     
  919.         itsFile->GetName(theName);
  920.         itsWindow->SetTitle(theName);
  921.         itsWindow->Select();            /* Don't forget to make the window active */
  922.     }
  923.     
  924.     CATCH
  925.     {
  926.         /*
  927.          * This exception handler will be executed if an exception occurs
  928.          * anywhere within the scope of the TRY block above.
  929.          * You should perform any cleanup of things that won't be needed
  930.          * since the document could not be opened. By convention,
  931.          * the creator of an object is responsible for sending it
  932.          * the Dispose message. This means that we should only dispose
  933.          * of things that would not be taken care of in Dispose.
  934.          * In this case, we just make sure that the Handle theData
  935.          * has been disposed of. The exception will propagate up to
  936.          * CApplications's exception handler, which handles displaying
  937.          * an error alert.
  938.          */
  939.          
  940.          if (theData) DisposHandle( theData);
  941.          
  942.     }
  943.     ENDTRY;
  944. }
  945.  
  946. /***
  947.  * FSOpenFile
  948.  *
  949.  *    When the user chooses Open╔ from the File menu, the OpenDocument()
  950.  *    method in your Application class will let the user choose a file
  951.  *    and then send a newly created document this message. The information
  952.  *    about the file is in the SFReply record.
  953.  *
  954.  *    In this method, you need to open the file and display its contents
  955.  *    in a window. This method uses the auxiliary window-building method.
  956.  *
  957.  ***/
  958.  
  959. void CHarvestDoc::FSOpenFile(char *name, short vRefNum, long dirID)
  960.  
  961. {
  962.     CDataFile    *theFile;
  963.     Handle        theData = NULL;
  964.     Str63        theName;
  965.     FInfo        fileInfo;
  966.     OSErr        theError;
  967.     
  968.     TRY
  969.     {
  970.     
  971.             /**
  972.              ** Create a file and send it a SFSpecify()
  973.              **    message to set up the name, volume, and
  974.              **    directory.
  975.              **
  976.              **/
  977.     
  978.         theFile = new(CDataFile);
  979.         theFile->IDataFile();
  980.         theFile->SpecifyHFS((unsigned char *) name,vRefNum,dirID);
  981.         theFile->GetMacFileInfo(&fileInfo);
  982.         if (fileInfo.fdType != 'Hprj') {
  983.             gProject = NULL;
  984.             return;
  985.         }
  986.             /**
  987.              **    Be sure to set the instance variable
  988.              **    so other methods can use the file if they
  989.              **    need to. This is especially important if
  990.              **    you leave the file open in this method.
  991.              **    If you close the file after reading it, you
  992.              **    should be sure to set itsFile to NULL.
  993.              **
  994.              **/
  995.     
  996.         itsFile = theFile;
  997.  
  998.             /**
  999.              **    Send the file an Open() message to
  1000.              **    open it. You can use the ReadSome() or
  1001.              **    ReadAll() methods to get the contents of the file.
  1002.              **
  1003.              **/
  1004.     
  1005.         theFile->Open(fsRdWrPerm);
  1006.         
  1007.             /**
  1008.              **    Make sure that the memory request to read
  1009.              **    the data from the file doesn't use up any
  1010.              **    of our rainy day fund and that the GrowMemory()
  1011.              **    method (in the application) knows that it's OK
  1012.              **    if we couldn't get enough memory.
  1013.              **
  1014.              **/
  1015.     
  1016.     
  1017.         theData = theFile->ReadAll();     /* ReadAll() creates the handle */
  1018.         
  1019.         if (!theData) {
  1020.             Failure(kSilentErr,0);
  1021.         }
  1022.         
  1023.         BuildWindow(theData);
  1024.     
  1025.         if (StdAppName[0] == 0) {
  1026.             itsFile->GetName(StdAppName);
  1027.         }
  1028.         if (StdAppName[StdAppName[0]] == '╣') {
  1029.             if (StdAppName[StdAppName[0]-1] == '.') {
  1030.                 StdAppName[0] -= 2;
  1031.             }
  1032.             else {
  1033.                 StdAppName[0] -= 1;
  1034.             }
  1035.         }
  1036.             /**
  1037.              **    In your application, you'll probably store
  1038.              **    the data in some form as an instance variable
  1039.              **    in your document class. For this example, there's
  1040.              **    no need to save it, so we'll get rid of it.
  1041.              **
  1042.              **/
  1043.     
  1044.         DisposHandle(theData);
  1045.         theData = NULL;
  1046.     
  1047.             /**
  1048.              **    In this implementation, we leave the file
  1049.              **    open. You might want to close it after
  1050.              **    you've read in all the data.
  1051.              **
  1052.              **/
  1053.     
  1054.         itsFile->GetName(theName);
  1055.         itsWindow->SetTitle(theName);
  1056.         itsWindow->Select();            /* Don't forget to make the window active */
  1057.     }
  1058.     
  1059.     CATCH
  1060.     {
  1061.         /*
  1062.          * This exception handler will be executed if an exception occurs
  1063.          * anywhere within the scope of the TRY block above.
  1064.          * You should perform any cleanup of things that won't be needed
  1065.          * since the document could not be opened. By convention,
  1066.          * the creator of an object is responsible for sending it
  1067.          * the Dispose message. This means that we should only dispose
  1068.          * of things that would not be taken care of in Dispose.
  1069.          * In this case, we just make sure that the Handle theData
  1070.          * has been disposed of. The exception will propagate up to
  1071.          * CApplications's exception handler, which handles displaying
  1072.          * an error alert.
  1073.          */
  1074.          
  1075.          if (theData) DisposHandle( theData);
  1076.          gProject = NULL;
  1077.          
  1078.     }
  1079.     ENDTRY;
  1080. }
  1081.  
  1082.  
  1083.  
  1084. /***
  1085.  * BuildWindow
  1086.  *
  1087.  *    This is the auxiliary window-building method that the
  1088.  *    NewFile() and OpenFile() methods use to create a window.
  1089.  *
  1090.  *    In this implementation, the argument is the data to display.
  1091.  *
  1092.  ***/
  1093.  
  1094. void CHarvestDoc::BuildWindow (Handle theData)
  1095.  
  1096. {
  1097.     CScrollPane        *theScrollPane;
  1098.     CHarvestPane    *theMainPane;
  1099.     Rect theRect = {75,175,300,175};
  1100.  
  1101.         /**
  1102.          **    First create the window and initialize
  1103.          **    it. The first argument is the resource ID
  1104.          **    of the window. The second argument specifies
  1105.          **    whether the window is a floating window.
  1106.          **    The third argument is the window's enclosure; it
  1107.          **    should always be gDesktop. The last argument is
  1108.          **    the window's supervisor in the Chain of Command;
  1109.          **    it should always be the Document object.
  1110.          **
  1111.          **/
  1112.     itsWindow = new(CWindow);
  1113.     itsWindow->IWindow(WINDHarvest, FALSE, gDesktop, this);
  1114.     
  1115.         /**
  1116.          **    After you create the window, you can use the
  1117.          **    SetSizeRect() message to set the window╒s maximum
  1118.          **    and minimum size. Be sure to set the max & min
  1119.          **    BEFORE you send a PlaceNewWindow() message to the
  1120.          **    decorator.
  1121.          **
  1122.          ** The default minimum is 100 by 100 pixels. The
  1123.          **    default maximum is the bounds of GrayRgn() (The
  1124.          **    entire display area on all screens.)
  1125.          **
  1126.          ** We'll use the defaults.
  1127.          **
  1128.          **/
  1129.     itsWindow->SetSizeRect(&theRect);
  1130.         /**
  1131.          ** Our window will contain a ScrollPane,
  1132.          ** which in turn will contain a Panorama.
  1133.          ** Now, let's create the ScrollPane.
  1134.          **/
  1135.  
  1136.     theScrollPane = new(CScrollPane);
  1137.     
  1138.         /**
  1139.          **    You can initialize a scroll pane two ways:
  1140.          **        1. You can specify all the values
  1141.          **           right in your code, like this.
  1142.          **        2. You can create a ScPn resource and
  1143.          **           initialize the pane from the information
  1144.          **           in the resource.
  1145.          **
  1146.          **/
  1147.  
  1148.     theScrollPane->IScrollPane(itsWindow, this, 10, 10, 0, 0,
  1149.                                 sizELASTIC, sizELASTIC,
  1150.                                 TRUE, TRUE, TRUE);
  1151.  
  1152.         /**
  1153.          **    The FitToEnclFrame() method makes the
  1154.          **    scroll pane be as large as its enclosure.
  1155.          **    In this case, the enclosure is the window,
  1156.          **    so the scroll pane will take up the entire
  1157.          **    window.
  1158.          **
  1159.          **/
  1160.  
  1161.     theScrollPane->FitToEnclFrame(TRUE, TRUE);
  1162.  
  1163.  
  1164.         /**
  1165.          **    itsMainPane is the document's focus
  1166.          **    of attention. Some of the standard
  1167.          **    classes (particularly CPrinter) rely
  1168.          **    on itsMainPane pointing to the main
  1169.          **    pane of your window.
  1170.          **
  1171.          **    itsGopher specifies which object
  1172.          ** should become the gopher when the document
  1173.          ** becomes active. By default
  1174.          **    the document becomes the gopher. It╒s
  1175.          **    likely that your main pane handles commands
  1176.          **    so you╒ll almost always want to set itsGopher
  1177.          **    to point to the same object as itsMainPane.
  1178.          **
  1179.          **    Note that the main pane is the
  1180.          **    panorama in the scroll pane and not
  1181.          **    the scroll pane itself.
  1182.          **
  1183.          **/
  1184.  
  1185.     theMainPane = new(CHarvestPane);
  1186.     theMainPane->IHarvestPane(theScrollPane, this);
  1187.         // finally initialize the table
  1188.         // insert some rows and columns into the new table
  1189.     
  1190.     itsMainPane = itsTable = theMainPane;
  1191.     itsTable->AddRow( 0, -1);
  1192.     itsTable->AddCol( 1, -1);
  1193.     itsTable->SetDblClickCmd(cmdOpenSourceFile);
  1194.     itsGopher = theMainPane;
  1195.     
  1196.         /**    The FitToEnclosure() method makes the pane
  1197.          **    fit inside the enclosure. The inside (or
  1198.          **    interior) of a scroll pane is defined as
  1199.          **    the area inside the scroll bars.
  1200.          **/
  1201.  
  1202.     theMainPane->FitToEnclosure(TRUE, TRUE);
  1203.  
  1204.         /**
  1205.          **    Send the scroll pane an InstallPanorama()
  1206.          ** message to associate the panorama with 
  1207.          ** the scroll pane.
  1208.          **
  1209.          **/
  1210.  
  1211.     theScrollPane->InstallPanorama(theMainPane);
  1212.     
  1213.         /**
  1214.          **    The Decorator is a global object that takes care
  1215.          **    of placing and sizing windows on the screen.
  1216.          **    You don't have to use it.
  1217.          **
  1218.          **/
  1219.  
  1220.     gDecorator->PlaceNewWindow(itsWindow);
  1221.             
  1222.     itsWindow->Select();
  1223.  
  1224.     if (theData) {
  1225.         if (GetHandleSize(theData))
  1226.             ReadFromHandle(theData);
  1227.     }
  1228. }
  1229.  
  1230. #define HWriteShort(h,i,val) if ((i+2)>=dataSize) SetHandleSize(h,dataSize*=2);BlockMove(&val,&((*(h))[(i)]),sizeof(short));i+=sizeof(short);
  1231. #define HWriteLong(h,i,val) if ((i+4)>=dataSize) SetHandleSize(h,dataSize*=2);BlockMove(&val,&((*(h))[(i)]),sizeof(long));i+=sizeof(long);
  1232.  
  1233. #define HReadShort(h,i,val) BlockMove(&((*(h))[(i)]),&val,sizeof(short));i+=sizeof(short);
  1234. #define HReadLong(h,i,val)  BlockMove(&((*(h))[(i)]),&val,sizeof(long));i+=sizeof(long);
  1235.  
  1236. #ifdef Undefined
  1237. #define HWriteShort(h,i,val) (*(h))[(i)] = HiByte((val));(*(h))[(i)+1] = LoByte((val));i+=2;
  1238. #define HWriteLong(h,i,val)    (*(h))[(i)] = HiByte((HiShort((val)))); \
  1239.                             (*(h))[(i)+1] = LoByte((HiShort((val)))); \
  1240.                             (*(h))[(i)+2] = HiByte((LoShort((val)))); \
  1241.                             (*(h))[(i)+3] = LoByte((LoShort((val))));i+=4;
  1242. #endif
  1243. #define HWriteCString(h,i,s) if ((i+strlen(s))>=dataSize) SetHandleSize(h,dataSize*=2);strcpy(&((*(h))[(i)]),s);i+=strlen(s)+1;
  1244. #define HWritePString(h,i,s) if ((i+*s)>=dataSize) SetHandleSize(h,dataSize*=2);CopyPString(s,((unsigned char *) &((*(h))[(i)])));i+=*s+1;
  1245.  
  1246. #ifdef Undefined
  1247. #define HReadShort(h,i,val) val = ((((int) ((*(h))[(i)])) << 8) | ((int) ((*(h))[(i)+1])));i+=2;
  1248. #define HReadLong(h,i,val) val = (((int) ((*(h))[(i)])) << 24) | (((int) ((*(h))[(i)+1])) << 16) \
  1249.                                 | (((int) ((*(h))[(i)+2])) << 8) | (((int) ((*(h))[(i)+3])));i+=4;
  1250. #endif
  1251.                                 
  1252. #define HReadCString(h,i,s) strcpy(s,&((*(h))[(i)]),s);i+=strlen(s)+1;
  1253. #define HReadPString(h,i,s) CopyPString(((unsigned char *) &((*(h))[(i)])),s);i+=*s+1;
  1254.  
  1255. Handle CHarvestDoc::WriteToHandle(void)
  1256. {
  1257.     long ndx = 0;
  1258.     long i;
  1259.     Handle theData;
  1260.     CSourceFile *aFile;
  1261.     Handle aHandle;
  1262.     long dataSize = 4000;    /* Danger - this should not be hard coded */
  1263.     long k2;
  1264.     short CountSourceFiles;
  1265.     
  1266.     theData = NewHandleClear(dataSize);
  1267.  
  1268.     aHandle = (Handle) itsOptions;
  1269.     BlockMove(*aHandle,(*theData + ndx),ndx += GetHandleSize(aHandle));
  1270.     
  1271.     CountSourceFiles = itsSourceFiles->GetNumItems();
  1272.     HWriteShort(theData,ndx,CountSourceFiles);
  1273.     HWriteLong (theData,ndx,itsSignature);
  1274.     HWriteLong (theData,ndx,itsPartition);
  1275.     HWriteShort(theData,ndx,StdAppVol);
  1276.     HWriteLong (theData,ndx,StdAppDir);
  1277.     HWritePString(theData,ndx,StdAppName);
  1278.     
  1279.     for (i=1;i<=CountSourceFiles;i++) {
  1280.         short k;
  1281.         aFile = (CSourceFile *) itsSourceFiles->NthItem(i);
  1282.         if (aFile->itsOptions) {
  1283.             k = 1;
  1284.             HWriteShort(theData,ndx,k);
  1285.             aHandle = (Handle) aFile->itsOptions;
  1286.             BlockMove(*aHandle,(*theData + ndx),ndx += GetHandleSize(aHandle));
  1287.         }
  1288.         else {
  1289.             k = 0;
  1290.             HWriteShort(theData,ndx,k);
  1291.         }
  1292.         HWriteShort(theData,ndx,aFile->itsKind);
  1293.         HWriteShort(theData,ndx,aFile->theFile->volNum);
  1294.         HWriteLong(theData,ndx,aFile->theFile->dirID);
  1295.         HWritePString(theData,ndx,aFile->theFile->name);
  1296.     }
  1297.     
  1298.     k2 = strlen(itsPrefix);
  1299.     HWriteLong(theData,ndx,k2);
  1300.     HWriteCString(theData,ndx,itsPrefix);
  1301.     k2 = 0;
  1302.     HWriteLong(theData,ndx,k2);
  1303.  
  1304.     return theData;
  1305. }
  1306.  
  1307. void CHarvestDoc::ReadFromHandle(Handle theData)
  1308. {
  1309.     long ndx = 0;
  1310.     long i;
  1311.     Handle aHandle;
  1312.     short CountSourceFiles;
  1313.     short flag;
  1314.     short vol;
  1315.     long dirID;
  1316.     long scratch;
  1317.     Str63 name;
  1318.     
  1319.     StdAppVol = itsFile->volNum;
  1320.     StdAppDir = itsFile->dirID;
  1321.     
  1322.     aHandle = (Handle) itsOptions;
  1323.     BlockMove((*theData + ndx),*aHandle,ndx += GetHandleSize(aHandle));
  1324.  
  1325.     HReadShort(theData,ndx,CountSourceFiles);
  1326.     HReadLong (theData,ndx,itsSignature);
  1327.     HReadLong (theData,ndx,itsPartition);
  1328.     HReadShort(theData,ndx,StdAppVol);
  1329.     HReadLong (theData,ndx,StdAppDir);
  1330.     HReadPString(theData,ndx,StdAppName);
  1331.     
  1332.     for (i=1;i<=CountSourceFiles;i++) {
  1333.         short kind;
  1334.         HReadShort(theData,ndx,flag);
  1335.         if (flag) {
  1336.             aHandle = (Handle) new CHarvestOptions;
  1337.             BlockMove(*aHandle,(*theData + ndx),ndx += GetHandleSize(aHandle));
  1338.         }
  1339.         HReadShort(theData,ndx,kind);
  1340.         HReadShort(theData,ndx,vol);
  1341.         HReadLong(theData,ndx,dirID);
  1342.         HReadPString(theData,ndx,name);
  1343.  
  1344.         if (kind == H_LibraryFile)
  1345.             AddLibraryFileHFS(name,vol,dirID);
  1346.         else if (kind == H_ResourceFile)
  1347.             AddResourceFileHFS(name,vol,dirID);
  1348.         else
  1349.             AddSourceFileHFS(name,vol,dirID);
  1350.     }
  1351.     
  1352.     HReadLong(theData,ndx,scratch);
  1353.     itsPrefix = (char *) icemalloc(scratch);
  1354.     HReadCString(theData,ndx,itsPrefix);
  1355.     HReadLong(theData,ndx,scratch);
  1356. }
  1357.  
  1358. /******************************************************************************
  1359.  Close {OVERRIDE}
  1360.  
  1361.         Close a Document
  1362.  ******************************************************************************/
  1363.  
  1364. Boolean    CHarvestDoc::Close(
  1365.     Boolean        quitting)                /* Is this part of a quit sequence?    */
  1366. {
  1367.     /* Ignore quitting -- We always save the file. */
  1368.  
  1369.     Handle theData;
  1370.     
  1371.         if (!itsFile) {
  1372.             /* We need to specify a file */
  1373.         }
  1374.         else {
  1375.             theData = WriteToHandle();
  1376.             ((CDataFile *) itsFile)->SetMark(0,fsFromStart);
  1377.             ((CDataFile *) itsFile)->WriteAll(theData);
  1378.             if (itsFile != NULL) {            /* Yes. Close associated file.        */
  1379.                 itsFile->Close();
  1380.                 itsFile = NULL;
  1381.             }
  1382.             DisposHandle(theData);
  1383.         }
  1384.     
  1385.         inherited::Close(quitting);
  1386.         gProject = NULL;
  1387.         return(TRUE);                    /* Document has been closed            */
  1388.         
  1389. }
  1390.     
  1391. /***
  1392.  * DoSave
  1393.  *
  1394.  *    This method handles what happens when the user chooses Save from the
  1395.  *    File menu. This method should return TRUE if the file save was successful.
  1396.  *    If there is no file associated with the document, you should send a
  1397.  *    DoSaveFileAs() message.
  1398.  *
  1399.  ***/
  1400.  
  1401. Boolean CHarvestDoc::DoSave(void)
  1402.  
  1403. {
  1404.         /**
  1405.          **    If you closed your file in your NewFile() method,
  1406.          **    you'll need a different way than this to determine
  1407.          **    if there's a file associated with your document.
  1408.          **
  1409.          **/
  1410.  
  1411.     if (itsFile == NULL)
  1412.         return(DoSaveFileAs());
  1413.     else {
  1414.             
  1415.         /**
  1416.          **    In your application, this is where you'd
  1417.          **    write out your file. if you left it open,
  1418.          **    send the WriteSome() or WriteAll() mesages
  1419.          **    to itsFile.
  1420.          **
  1421.          **/
  1422.             
  1423.         dirty = FALSE;                    /* Document is no longer dirty        */
  1424.         gBartender->DisableCmd(cmdSave);
  1425.         return(TRUE);                    /* Save was successful                */
  1426.     }
  1427. }
  1428.  
  1429.  
  1430. /***
  1431.  * DoSaveAs
  1432.  *
  1433.  *    This method handles what happens when the user chooses Save As╔ from
  1434.  *    File menu. The default DoCommand() method for documents sends a DoSaveFileAs()
  1435.  *    message which displays a standard put file dialog and sends this message.
  1436.  *    The SFReply record contains all the information about the file you're about
  1437.  *    to create.
  1438.  *
  1439.  ***/
  1440.  
  1441. Boolean CHarvestDoc::DoSaveAs(SFReply *macSFReply)
  1442.  
  1443. {
  1444.         /**
  1445.          **    If there's a file associated with this document
  1446.          **    already, close it. The Dispose() method for files
  1447.          **    sends a Close() message to the file before releasing
  1448.          **    its memory.
  1449.          **
  1450.          **/
  1451.          
  1452.     if (itsFile != NULL)
  1453.         itsFile->Dispose();
  1454.  
  1455.  
  1456.         /**
  1457.          **    Create a new file, and then save it normally.
  1458.          **
  1459.          **/
  1460.  
  1461.     itsFile = new(CDataFile);
  1462.     ((CDataFile *)itsFile)->IDataFile();
  1463.     itsFile->SFSpecify(macSFReply);
  1464.     itsFile->CreateNew(gSignature, 'TEXT');
  1465.     itsFile->Open(fsRdWrPerm);
  1466.     
  1467.     itsWindow->SetTitle(macSFReply->fName);
  1468.  
  1469.     return( DoSave() );
  1470. }
  1471.  
  1472.  
  1473. /***
  1474.  * DoRevert
  1475.  *
  1476.  *    If your application supports the Revert command, this method
  1477.  *    should close the current file (without writing anything out)
  1478.  *    and read the last saved version of the file.
  1479.  *
  1480.  ***/
  1481.  
  1482. void CHarvestDoc::DoRevert(void)
  1483.  
  1484. {
  1485. }
  1486.  
  1487. Boolean CHarvestDoc::BringUpToDate(void) {
  1488.     int CountSourceFiles;
  1489.     int i;
  1490.     CSourceFile *aFile;
  1491.     Boolean result;
  1492.     
  1493.     result = TRUE;
  1494.  
  1495.     CountSourceFiles = itsSourceFiles->GetNumItems();
  1496.     for (i=1;i<=CountSourceFiles;i++) {
  1497.         aFile = (CSourceFile *) itsSourceFiles->NthItem(i);
  1498.         if (aFile->itsKind == H_SourceFile) {
  1499.             if (aFile->GetSourceModDate() >= aFile->GetObjectModDate()) {
  1500.                 if (!aFile->Compile()) {
  1501.                     result = FALSE;
  1502.                 }
  1503.             }
  1504.         }
  1505.     }
  1506.     return result;
  1507. }
  1508.  
  1509. void
  1510. CopyAllResources(CSourceFile *aFile,short theApp)
  1511. {
  1512.         /* Now we copy all resources from theResFile to theApp */
  1513.         short typeCount;
  1514.         short resCount;
  1515.         short j;
  1516.         short k;
  1517.         ResType aType;
  1518.         Handle aRez;
  1519.         Handle dupRez;
  1520.         short resID;
  1521.         Str255 resName;
  1522.         short theResFile;
  1523.         ResType type2;
  1524.         short resAttrs;
  1525.  
  1526.         theResFile = HOpenResFile(aFile->theFile->volNum,aFile->theFile->dirID,aFile->theFile->name,1);
  1527.         UseResFile(theResFile);
  1528.         typeCount = Count1Types();
  1529.         for (j=1;j<=typeCount;j++) {
  1530.             UseResFile(theResFile);
  1531.             Get1IndType(&aType,j);
  1532.             resCount = Count1Resources(aType);
  1533.             for (k=1;k<=resCount;k++) {
  1534.                 UseResFile(theResFile);
  1535.                 aRez = Get1IndResource(aType,k);
  1536.                 GetResInfo(aRez,&resID,&type2,resName);
  1537.                 resAttrs = GetResAttrs(aRez);
  1538.                 DetachResource(aRez);
  1539.                 UseResFile(theApp);
  1540.                 dupRez = Get1Resource(aType,resID);
  1541.                 if (!dupRez) {
  1542.                     AddResource(aRez,aType,resID,resName);
  1543.                     SetResAttrs(aRez,resAttrs);
  1544.                     ChangedResource(aRez);
  1545.                 }
  1546.             }
  1547.         }
  1548.         CloseResFile(theResFile);
  1549. }
  1550.  
  1551. Boolean CHarvestDoc::DoLink(void)
  1552. {
  1553. #ifdef HDEBUG
  1554.     extern FILE *dumpFile;
  1555. #endif
  1556.  
  1557.     LinkerFileVia_t                 curf;
  1558.     int                             UserAbort = 0;
  1559.     InFileVia_t                     curin;
  1560.     LinkerFileVia_t                 files = NULL;
  1561.  
  1562.     char                            objname[64];
  1563.     char                            msg[128];
  1564.     char                            err[64];
  1565.     char                            errname[64];
  1566.     CursHandle                      curs;
  1567.     Str63 fname;
  1568.     int CountSourceFiles;
  1569.     int i;
  1570.     CDataFile *objFile;
  1571.     CSourceFile *aFile;
  1572.     CWindow *theWindow;
  1573.     extern unsigned short NextSegID;
  1574.     char mesg[64];
  1575.  
  1576.     LinkErrorCount = 0;
  1577.  
  1578. #ifdef HDEBUG
  1579.     dumpFile = fopen("Harvest C Debug Info","w");
  1580. #endif
  1581.  
  1582.     gCurSourceFile = NULL;
  1583.     gErrs = new CErrorLog;
  1584.     gErrs->IErrorLog();
  1585.     gErrs->BeginDialog();
  1586.  
  1587.     UserAbort = 0;
  1588.     
  1589.     gApplication->SpinCursor();
  1590.     
  1591.     NextSegID = 2;
  1592.  
  1593.       theWindow = gErrs->GetWindow();
  1594.     sprintf(mesg,"Linking %#s",StdAppName);
  1595. #ifdef HDEBUG
  1596.     fprintf(dumpFile,"%s\n",mesg);
  1597. #endif
  1598.     c2pstr(mesg);
  1599.     theWindow->SetTitle((unsigned char *) mesg);
  1600.  
  1601.     CountSourceFiles = itsSourceFiles->GetNumItems();
  1602.     for (i=1;i<=CountSourceFiles;i++) {
  1603.         gApplication->SpinCursor();
  1604.         aFile = (CSourceFile *) itsSourceFiles->NthItem(i);
  1605.         if (aFile->itsKind != H_ResourceFile) {
  1606.             objFile = aFile->GetObjectFile();
  1607.             if (objFile->ExistsOnDisk()) {
  1608.                 CopyPString(objFile->name,fname);
  1609.                 p2cstr(fname);
  1610.                    curf = ReadObjectFile((char *) fname, objFile->volNum, objFile->dirID);
  1611.             }
  1612.             if (curf) {
  1613.                 Via(curf)->next = files;
  1614.                 files = curf;
  1615.             } else {
  1616.                 sprintf(err, "Unable to access file %s", objname);
  1617.                 LinkerError(err);
  1618.             }
  1619.         }
  1620.     }
  1621.     if (files && !LinkErrorCount) {
  1622.         ResolveAllReferences(files);
  1623.         /* TODO Smart link */
  1624.         AssignMPWOffsets(files);
  1625.         AdjustAllReferences(files);
  1626.     }
  1627.     if (files && !LinkErrorCount) {
  1628.         Str63 cname;
  1629.         CopyPString(StdAppName,cname);
  1630.         p2cstr(cname);
  1631.         gErrs->Hprintf("References resolved ok");
  1632.         if (FlushLink((char *) cname, StdAppVol, StdAppDir, files)) {
  1633.             short theApp;
  1634.             short theResFile;
  1635.             theApp = HOpenResFile(StdAppVol, StdAppDir, StdAppName, 2);
  1636.             if (theApp == -1) {
  1637.                 LinkerError("Couldn't open app file for adding resources");
  1638.             }
  1639.             else {
  1640.                 for (i=1;i<=CountSourceFiles;i++) {
  1641.                     gApplication->SpinCursor();
  1642.                     aFile = (CSourceFile *) itsSourceFiles->NthItem(i);
  1643.                     if (aFile->itsKind == H_ResourceFile) {
  1644.                         CopyAllResources(aFile,theApp);
  1645.                     }
  1646.                 }
  1647.                 CloseResFile(theApp);
  1648.             }
  1649.         }
  1650.     }
  1651.     else
  1652.         LinkerError("Link errors prevent completion");
  1653.         
  1654.     KillLinkFiles(files);
  1655.     KillSegments(SegmentList);
  1656.     KillModPacks(theDATA.ModuleList);
  1657.     KillImage(theDATA.Image);
  1658.  
  1659. #ifdef HDEBUG
  1660.     fclose(dumpFile);
  1661. #endif
  1662.  
  1663.     InitCursor();
  1664. }
  1665.  
  1666. /******************************************************************************
  1667.  PickAppName
  1668.  
  1669.         Put up a standard put file dialog box to allow the user to
  1670.         specify a new name under which to save the linked application.
  1671.  ******************************************************************************/
  1672.  
  1673. Boolean    CHarvestDoc::PickAppName(void)
  1674. {
  1675.     Point            corner;                /* Top left corner of dialog box    */
  1676.     Str255            origName;            /* Default name for file            */
  1677.     StringHandle    prompt;                /* Prompt string                    */
  1678.     SFReply macSFReply;
  1679.     CDataFile *aFile;
  1680.     FSSpec fileSpec;
  1681.         
  1682.                                         /* Center dialog box on the screen    */
  1683.     FindDlogPosition('DLOG', putDlgID, &corner);
  1684.     
  1685.     CopyPString(StdAppName,origName);
  1686.     
  1687.     prompt = GetString(1000);
  1688.     FailNILRes( prompt);
  1689.     
  1690.     MoveHHi( (Handle) prompt);
  1691.     HLock((Handle) prompt);
  1692.     SFPPutFile(corner, *prompt, origName, NULL, &macSFReply, putDlgID, NULL);
  1693.     HUnlock((Handle) prompt);
  1694.     if (macSFReply.good) {
  1695.         aFile = new CDataFile;
  1696.         aFile->IDataFile();
  1697.         aFile->SFSpecify(&macSFReply);
  1698.         aFile->GetFSSpec(&fileSpec);
  1699.         StdAppVol = fileSpec.vRefNum;
  1700.         StdAppDir = fileSpec.parID;
  1701.         CopyPString(fileSpec.name,StdAppName);
  1702.         return TRUE;
  1703.     } 
  1704.     else return FALSE;
  1705. }
  1706.  
  1707.  
  1708. ProcessSerialNumber CHarvestDoc::RunApp(void)
  1709. {
  1710.     FSSpec theApp;
  1711.     CFile *theFile;
  1712.     ProcessSerialNumber defaultResult = {0};
  1713.     FSMakeFSSpec(StdAppVol,
  1714.                 StdAppDir,
  1715.                 StdAppName,
  1716.                 &theApp);
  1717.     theFile = new CFile;
  1718.     theFile->IFile();
  1719.     theFile->SpecifyFSSpec(&theApp);
  1720.     if (theFile->ExistsOnDisk()) {
  1721.         LaunchParamBlockRec myLaunchParams;
  1722.         OSErr launchErr;
  1723.         ForgetObject(theFile);
  1724.         myLaunchParams.launchBlockID = extendedBlock;
  1725.         myLaunchParams.launchEPBLength = extendedBlockLen;
  1726.         myLaunchParams.launchFileFlags = 0;
  1727.         myLaunchParams.launchControlFlags = launchContinue + launchNoFileFlags;
  1728.         myLaunchParams.launchAppSpec = &theApp;
  1729.         myLaunchParams.launchAppParameters = NULL;
  1730.         launchErr = LaunchApplication(&myLaunchParams);
  1731.         FailOSErr(launchErr);
  1732.         return myLaunchParams.launchProcessSN;
  1733.     }
  1734.     else {
  1735.         SysBeep(1);
  1736.     }
  1737.     ForgetObject(theFile);
  1738.     return defaultResult;
  1739. }
  1740.  
  1741. void CHarvestDoc::Clean(void) {
  1742.     int CountSourceFiles;
  1743.     int i;
  1744.     CSourceFile *aFile;
  1745.     CDataFile *objFile;
  1746.  
  1747.     CountSourceFiles = itsSourceFiles->GetNumItems();
  1748.     for (i=1;i<=CountSourceFiles;i++) {
  1749.         aFile = (CSourceFile *) itsSourceFiles->NthItem(i);
  1750.         if (aFile->itsKind == H_SourceFile) {
  1751.             objFile = aFile->GetObjectFile();
  1752.             if (objFile->ExistsOnDisk())
  1753.                 objFile->ThrowOut();
  1754.         }
  1755.     }
  1756. }
  1757.  
  1758. Boolean CHarvestDoc::Link(void) {
  1759.     if (PickAppName()) {
  1760.         if (BringUpToDate()) {
  1761.             return DoLink();
  1762.         }
  1763.         return FALSE;
  1764.     }
  1765.     return FALSE;
  1766. }
  1767.  
  1768. Boolean CHarvestDoc::CheckLink(void) {
  1769.     SysBeep(1);
  1770. }
  1771.  
  1772. Boolean EqualPStrings(unsigned char *a,unsigned char *b) {
  1773.     int i,len;
  1774.     if (*a == *b) {
  1775.         len = *a;
  1776.         i = 1;
  1777.         while (a[i] == b[i]) {
  1778.             i++;
  1779.             if (i>len) return TRUE;
  1780.         }
  1781.     }
  1782.     return FALSE;
  1783. }
  1784.  
  1785. int CHarvestDoc::FindFile(char *name,short vRefNum,long dirID)
  1786. {
  1787.     /* Locate the given file, return its index in the list */
  1788.     int CountSourceFiles;
  1789.     int i;
  1790.     CSourceFile *aFile;
  1791.     CDataFile *theFile;
  1792.  
  1793.     CountSourceFiles = itsSourceFiles->GetNumItems();
  1794.     for (i=1;i<=CountSourceFiles;i++) {
  1795.         aFile = (CSourceFile *) itsSourceFiles->NthItem(i);
  1796.         theFile = aFile->theFile;
  1797.         if (theFile->volNum == vRefNum) {
  1798.             if (theFile->dirID == dirID) {
  1799.                 if (EqualPStrings((unsigned char *) name,theFile->name)) {
  1800.                     return i;
  1801.                 }
  1802.             }
  1803.         }
  1804.     }
  1805.     return 0;
  1806. }
  1807.  
  1808.